package com.kunya.common.util;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * FTP服务类
 * @author suimg
 * @date 2018/7/13 9:21
 */
@Slf4j
public class FTPUtil implements AutoCloseable{

    /**
     * 连接主机地址
     */
    private static final String host=PropertiesUtil.getProperty("com.kunya.ftp.host");

    /**
     * 端口号
     */
    private static final Integer port=PropertiesUtil.getProperty("com.kunya.ftp.port",Integer.class);

    /**
     * 用户名
     */
    private static final String username=PropertiesUtil.getProperty("com.kunya.ftp.username");

    /**
     * 密码
     */
    private static final String password=PropertiesUtil.getProperty("com.kunya.ftp.password");;

    /**
     * 文件编码
     */
    private static final String encoding = System.getProperty("file.encoding");

    /**
     * 客户端
     */
    private static FTPClient ftpClient;


    /**
     * 登录到FTP
     * @throws IOException
     */
    private static void login() throws IOException {
        ftpClient = new FTPClient();
        try {
            ftpClient.connect(host,port);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.setControlEncoding(encoding);
            ftpClient.setBufferSize(1024*1024);
            FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);//解决中文乱码
            conf.setServerLanguageCode("zh");
            ftpClient.configure(conf);
        } catch (SocketException e) {
            e.printStackTrace();
            throw new RuntimeException("FTP连接失败！", e);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("FTP客户端出错！", e);
        }
        ftpClient.login(username, password);
        log.info("Login ftp at:{}",new Date());
    }

    /**
     * 退出FTP
     * @throws IOException
     */
    private static void logout() throws IOException {
        ftpClient.logout();
        ftpClient.disconnect();
        log.info("Logout ftp at:{}",new Date());
    }

    /**
     * 针对在LUNUX FTP服务器下不能同时创建多级目录 所写的方法
     * @param path
     * @throws IOException
     */
    private static void cd(String path) throws IOException {
        log.info("change work directory:{}",path);
        if(!ftpClient.changeWorkingDirectory(path)){
            log.info("change directory faild,going to step make mode");
            for (String dir : path.split("/")) {
                if(dir!=""){
                    cd0(dir);
                }
            }
        }
    }

    /**
     * 切换目录
     * 如果目录不存在就尝试创建
     * @param path
     * @throws IOException
     */
    private static void cd0(String path) throws IOException{
        log.info("[step make mode]:change work directory:{}",path);
        if(!ftpClient.changeWorkingDirectory(path)){
            log.info("[step make mode]:directory is not exists,making");
            if(!ftpClient.makeDirectory(path)){
                throw new RuntimeException("make directory:`{"+path+"}` faild");
            }
            cd0(path);
        }
    }

    /**
     * 删除文件
     * @param name
     * @throws IOException
     */
    public static void del(String name) throws IOException{
        try{
            login();
            ftpClient.deleteFile(name);
        }finally {
            logout();
        }
    }

    /**
     * 上传文件到指定目录
     * @param is
     * @param path
     * @param fileName
     * @throws IOException
     */
    public static void upload(InputStream is,String path,String fileName) throws IOException{
        try{
            login();
            cd(path);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.storeFile(fileName,is);
        }finally {
            logout();
        }
    }

    /**
     * 上传文件到指定目录
     * @param file
     * @param path
     * @param fileName
     * @throws IOException
     */
    public static void upload(File file,String path,String fileName) throws IOException {
        upload(new FileInputStream(file),path,fileName);
    }

    /**
     * 从FTP下载文件
     * @param path
     * @param fileName
     * @return
     */
    public static File downloadFile(String path,String fileName) throws IOException{
        try {
            login();
            File file=File.createTempFile("FTP_TMPFILE",".bin");
            cd(path);
            OutputStream os = new FileOutputStream(file);
            ftpClient.retrieveFile(fileName, os);
            return file;
        }finally {
            logout();
        }

    }

    /**
     * 获取文件的输入流
     * @param path
     * @param fileName
     * @return
     */
    public static InputStream getFileInputStream(String path,String fileName) throws IOException{
        return new FileInputStream(downloadFile(path,fileName));
    }

    /**
     * 获取目录下的所有文件名称
     * @param path
     * @return
     */
    public static List<String> getFileNameList(String path) throws IOException{
        try {
            login();
            List<String> fileNameList=new ArrayList<>();
            FTPFile[] files = ftpClient.initiateListParsing(path).getFiles();
            for (FTPFile file: files) {
                log.info(file.toString());
                fileNameList.add(file.getName());
            }
            return fileNameList;
        }finally {
            logout();
        }
    }

    @Override
    public void close() throws Exception {
        ftpClient.disconnect();
    }
}
